<template>
  <div>
    <Form
      ref="userForm"
      :model="userForm"
      :rules="ruleValidate"
      :label-position="label.position"
      :label-width="label.width"
    >
      <fieldset class="line-field">
        <legend>{{ isModifiedRoles ? '用户权限' : '用户信息' }}</legend>
        <div v-if="!isModifiedRoles">
          <FormItem label="用户身份" prop="identity">
            <RadioGroup v-model="userForm.identity" @on-change="onChangeIdentity">
              <Radio label="Teacher" :disabled="isModified">教师</Radio>
              <Radio label="Student" :disabled="isModified" style="margin-left: 20px;">学生</Radio>
            </RadioGroup>
          </FormItem>
          <FormItem label="所属学院" prop="department">
            <Select
              v-model="userForm.department"
              :disabled="!user.access.some(item => { return ['ROLE_ROOT', 'ROLE_SCHOOL_ADMIN'].indexOf(item) > -1 }) || isModified"
              v-if="user.access.some(item => { return ['ROLE_ROOT', 'ROLE_SCHOOL_ADMIN'].indexOf(item) > -1 }) && !isModified"
              filterable
              :enabledPreventOverflow="enabledPreventOverflow"
              :not-found-text="loading.department ? '查询学院中，请稍等...' : '无可选学院'"
              placeholder="请选择教师所属学院"
              @on-change="onSelectDepartment"
            >
              <Option
                v-for="(option, index) in options.department"
                :value="option"
                :key="index"
              >{{option}}</Option>
            </Select>
            <Input v-else v-model="userForm.department" readonly placeholder="用户所属学院" />
          </FormItem>
          <FormItem label="工号" prop="code" v-if="isModified">
            <Input v-model="userForm.code" placeholder="请输入用户的工号" :readonly="isModified" />
          </FormItem>
          <FormItem label="教师" prop="teacher_code" v-else-if="userForm.identity === 'Teacher'">
            <Select
                v-model="userForm.teacher_code"
                filterable
                :enabledPreventOverflow="enabledPreventOverflow"
                :not-found-text="loading.teacher ? '查询教师中，请稍等...' : '无可选教师'"
                :label-in-value="true"
                @on-change="onSelectTeacher"
                placeholder="请先选择教师">
                <Option v-for="(option, index) in options.teacher" :value="option.code" :key="index">{{option.name}}</Option>
            </Select>
          </FormItem>
          <FormItem label="学号" prop="student_code" v-else>
            <Input v-model="userForm.student_code" placeholder="请输入用户的工号" :readonly="isModified" />
          </FormItem>
          <FormItem label="姓名" prop="name" v-if="userForm.identity === 'Student' || isModified">
            <Input v-model="userForm.name" placeholder="请输入用户姓名" :readonly="isModified" />
          </FormItem>
          <FormItem label="邮箱" prop="email">
            <Input v-model="userForm.email" placeholder="请输入用户的邮箱" />
          </FormItem>
          <FormItem label="手机号">
            <Input v-model="userForm.tel" placeholder="请输入用户的手机号" />
          </FormItem>
          <FormItem class="ivu-form-item-required" label="状态" prop="enabled">
            <RadioGroup v-model="userForm.enabled">
              <Radio label="true">正常</Radio>
              <Radio label="false" style="margin-left: 20px;">禁用</Radio>
            </RadioGroup>
          </FormItem>
        </div>
        <FormItem label="权限" prop="roles">
          <p style="color: #f36a31;" v-if="loading.roles"><Icon type="ios-loading" class="spin-icon-load"/><span>获取ROLE角色分组中，请稍等...</span></p>
          <p style="color: #f36a31;" v-else-if="options.roles.length < 1"><Icon type="ios-alert-outline" size="22" style="margin-right: 10px; margin-bottom: 3px;"/><span>抱歉，暂无ROLE角色分组，请关闭重新打开重试.</span></p>
          <CheckboxGroup v-else v-model="userForm.roles">
            <Checkbox v-for="item in options.roles" :key="item" :label="item" style="margin-right: 15px" :disabled="'ROLE_USER' === item">{{ options.oriRoles[item] }}</Checkbox>
          </CheckboxGroup>
        </FormItem>
        <div class="text-center" v-if="isModifiedRoles">
          <Poptip
              confirm
              title="确定修改权限吗？"
              word-wrap
              width="180"
              @on-ok="handleSaveRoles()"
              class="text-left"
              :options="popperOpts">
              <Button type="success" class="mr-20">
                <span>修改权限</span>
              </Button>
          </Poptip>
          <Poptip
              confirm
              title="数据将不可恢复，确定重置权限吗？"
              word-wrap
              width="180"
              @on-ok="handleResetRoles()"
              class="text-left"
              :options="popperOpts">
            <Button style="margin-left: 8px">重置权限</Button>
          </Poptip>
        </div>
        <div class="text-center" v-else>
          <Poptip
              confirm
              title="确定提交表单吗？"
              word-wrap
              width="180"
              @on-ok="handleSaveUser('userForm')"
              class="text-left"
              :options="popperOpts">
              <Button type="success" class="mr-20">
                <span>提交表单</span>
              </Button>
          </Poptip>
          <Poptip
              confirm
              title="数据将不可恢复，确定重置表单吗？"
              word-wrap
              width="180"
              @on-ok="handleReset('userForm')"
              class="text-left"
              :options="popperOpts">
            <Button style="margin-left: 8px">重置表单</Button>
          </Poptip>
        </div>
      </fieldset>
    </Form>
    <Spin fix v-if="loading.submit">
        <Icon type="ios-loading" size=18 class="spin-icon-load"></Icon>
        <div>{{ loadingTip }}</div>
    </Spin>
  </div>
</template>
<script>
import { mapActions } from 'vuex'
import { trim } from '@/libs/tools'
import { getInstituteList, getTeacherList, submitSaveUser, getUserByCode, updateUserRoles } from '@/api/user-mgmt'
export default {
  name: 'UserSave',
  data () {
    return {
      options: {
        department: [],
        teacher: [],
        roles: [],
        oriRoles: {
          'ROLE_ROOT': '系统管理员',
          'ROLE_SCHOOL_ADMIN': '校级管理员',
          'ROLE_INSTITUTE_ADMIN': '学院管理员',
          'ROLE_TEACHER': '教师',
          'ROLE_STUDENT_ASSISTANT': '学生助理',
          'ROLE_STUDENT': '学生',
          'ROLE_USER': '普通用户'
        }
      },
      loading: {
        department: true,
        teacher: false,
        roles: true,
        submit: false,
        fill: false
      },
      // 当前登录用户相关信息
      user: {
        code: '',
        name: '',
        access: [],
        department: ''
      },
      userForm: {
        id: null,
        department: '',
        teacher_code: '',
        teacher_name: '',
        student_code: '',
        code: null,
        name: null,
        tel: null,
        email: null,
        // 用户状态
        enabled: 'true',
        // 身份：教师 Teacher，学生 Student
        identity: 'Teacher',
        // 权限数组
        roles: ['ROLE_TEACHER', 'ROLE_USER']
      },
      // 暂时存储切换前的用户信息
      temp: {
        roles: {
          teacher: ['ROLE_TEACHER', 'ROLE_USER'],
          student: ['ROLE_STUDENT', 'ROLE_USER']
        }
      },
      // 被修改的用户的信息
      beModifiedUser: {},
      ruleValidate: {
        department: [
          {required: true, message: '学院不能为空', trigger: 'change'}
        ],
        code: [
          {required: true, message: '工号不能为空', trigger: 'blur'}
        ],
        teacher_code: [
          {required: true, message: '请选择教师', trigger: 'change'}
        ],
        student_code: [
          {required: true, message: '学号不能为空', trigger: 'blur'}
        ],
        name: [
          {required: true, message: '姓名不能为空', trigger: 'blur'}
        ],
        tel: [
          {required: true, message: '手机号不能为空', trigger: 'blur'}
        ],
        email: [
          {required: false, type: 'email', message: '邮箱格式不正确', trigger: 'blur'}
        ],
        identity: [
          {required: true, message: '请选择用户身份', trigger: 'change'}
        ],
        enabled: [
          {required: true, message: '请选择用户身份', trigger: 'change'}
        ],
        roles: [
          {required: true, type: 'array', min: 1, message: '至少选择一个权限', trigger: 'change'}
        ]
      },
      label: {
        position: 'left',
        width: 100
      },
      // 是否可以重新选择学院，学院拆了之后，可能有旧学院存在用户信息中，需要重新选择学院
      reChooseInstitute: false,
      // Select选择器的下拉列表是否吸附，默认为true，吸附
      enabledPreventOverflow: false,
      popperOpts: {
        modifiers: {
          preventOverflow: {
            // 边界元素: scrollParent, window, viewport or any DOM element. 默认iview默认window
            boundariesElement: 'scrollParent'
          }
        }
      }
    }
  },
  props: {
    // 当前是否为修改状态
    isModified: {
      type: Boolean,
      default: false
    },
    // 被修改用户的id
    userId: {
      type: Number,
      default: null
    },
    // 被修改用户的工号
    userCode: {
      type: String,
      default: null
    },
    // 是否为修改权限
    isModifiedRoles: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    ...mapActions(['getUserInfo']),
    // 获取学院列表
    async getInstituteOptions () {
      this.loading.department = true
      let options = []
      try {
        let res = await getInstituteList()
        res = res.data
        if (res.code && res.data.length > 0) {
          options = res.data
        } else {
          this.$Notice.error({
            title: res.code ? '暂无学院' : '获取学院列表失败',
            desc: res.code ? '暂无可选学院，请刷新后重试' : res.info
          })
          options = []
        }
      } catch (error) {
        console.log(error)
        this.$Notice.error({
          title: '获取学院列表失败',
          desc: error
        })
        options = []
      }
      this.loading.department = false
      return options
    },
    // 获取ROLE类型
    async getRolesOptions () {
      this.loading.roles = true
      let options = {}
      try {
        let res = await getRolesType()
        res = res.data
        if (res.code && res.data !== {}) {
          options = res.data
        } else {
          this.$Notice.error({
            title: res.code ? '暂无ROLE角色' : '获取ROLE角色失败',
            desc: res.code ? '暂无可选ROLE角色，请刷新后重试' : res.info
          })
        }
      } catch (error) {
        console.log(error)
        this.$Notice.error({
          title: '获取ROLE权限分组失败',
          desc: error
        })
      }
      this.loading.roles = false
      return options
    },
    // 获取教师列表
    async getTeacherOptions (department) {
      this.loading.teacher = true
      let options = []
      try {
        let res = await getTeacherList(department)
        res = res.data
        if (res.code) {
          if (res.data.length > 0) {
            options = res.data
          } else {
            this.$Notice.error({
              title: '无匹配数据',
              desc: '该学院暂无可选教师，请选择其他学院'
            })
            options = []
          }
        } else {
          this.$Notice.error({
            title: '获取教师列表失败',
            desc: res.info
          })
          options = []
        }
      } catch (error) {
        console.log(error)
        this.$Notice.error({
          title: '获取教师列表失败',
          desc: error
        })
        options = []
      }
      this.loading.teacher = false
      return options
    },
    // created生命周期内的获取学院和教师列表
    async createdHandleOptions () {
      this.loading.roles = true
      let tempRoles = this.options.oriRoles
      this.options.roles = Object.keys(tempRoles).filter(key => {
        return !this.ifDisableThisRoleCheckbox(key)
      })
      this.$nextTick(() => {
        this.loading.roles = false
      })
      if (
        this.user.access.some(item => {
          return ['ROLE_ROOT', 'ROLE_SCHOOL_ADMIN'].indexOf(item) > -1
        })
      ) {
        try {
          // 校级管理员可以获取所有学院
          this.options.department = await this.getInstituteOptions()
          if (this.options.department.length <= 0) {
            return false
          }
        } catch (error) {
          this.options.department = [this.user.department]
          this.$Notice.error({
            title: '获取学院列表失败',
            desc: error
          })
        }
      } else {
        // 非校级管理员
        this.options.department = [this.user.department]
      }
      if (!this.isModified) {
        this.userForm.department = this.user.department
        if (this.userForm.identity === 'Teacher') {
          this.userForm.roles.push('ROLE_TEACHER')
        } else if (this.userForm.identity === 'Student') {
          this.userForm.roles.push('ROLE_STUDENT')
        }
        try {
          this.options.teacher = []
          this.options.teacher = await this.getTeacherOptions(this.userForm.department)
        } catch (error) {
          this.options.teacher = []
          this.$Notice.error({
            title: '获取教师列表失败',
            desc: error
          })
        }
      }
    },
    // 选择身份的回调事件
    onChangeIdentity (value) {
      if (value === 'Teacher') {
        this.arrayRemoveValue(this.options.roles, 'ROLE_STUDENT_ASSISTANT')
        this.arrayRemoveValue(this.options.roles, 'ROLE_STUDENT')
        // 把现在的旧值暂存到其他变量
        this.temp.roles.student = this.userForm.roles
        // 赋值旧的教师权限
        this.userForm.roles = this.temp.roles.teacher
      } else {
        this.options.roles.splice(-1, 0, 'ROLE_STUDENT_ASSISTANT')
        this.options.roles.splice(-1, 0, 'ROLE_STUDENT')
        this.temp.roles.teacher = this.userForm.roles
        this.userForm.roles = this.temp.roles.student
      }
    },
    // 选择学院的回调
    async onSelectDepartment (value) {
      if (value) {
        this.userForm.teacher_code = this.userForm.teacher_name = ''
        this.options.teacher = []
        this.options.teacher = await this.getTeacherOptions(value)
      }
    },
    // 选择教师的回调事件
    onSelectTeacher (teacher) {
      if (teacher) {
        this.userForm.teacher_name = teacher.label
        this.userForm.teacher_code = teacher.value
      }
    },
    // 是否禁用当前权限的checkbox
    ifDisableThisRoleCheckbox (role) {
      /**
       * 1. !this.user.access.some(item => { return ['ROLE_ROOT', 'ROLE_SCHOOL_ADMIN', 'ROLE_INSTITUTE_ADMIN'].indexOf(item) > -1 }) 只要不是 系统 / 校级 / 院级管理员，都不能修改别人的权限
       * 2. role === 'ROLE_ROOT' 系统管理员均是不可修改的
       * 3. this.userForm.identity === 'Teacher' && ['ROLE_STUDENT_ASSISTANT', 'ROLE_STUDENT'].indexOf(role) > -1 教师没有 学生助理 和 学生 这两个权限
       * 4. this.user.access.indexOf('ROLE_ROOT') > -1 系统管理员除‘系统管理员’外，均可修改
       * 5. this.user.access.indexOf('ROLE_SCHOOL_ADMIN') > -1 如果是校级管理员，则不可编辑 系统管理员 和 校级管理员权限
       * 6. this.user.access.indexOf('ROLE_INSTITUTE_ADMIN') > -1 院级管理员不可编辑 系统、校级、院级管理员
       * 7. 其余剩下的均可修改
       */
      if (!this.user.access.some(item => { return ['ROLE_ROOT', 'ROLE_SCHOOL_ADMIN', 'ROLE_INSTITUTE_ADMIN'].indexOf(item) > -1 }) || role === 'ROLE_ROOT') {
        return true
      }
      if (this.userForm.identity === 'Teacher' && ['ROLE_STUDENT_ASSISTANT', 'ROLE_STUDENT'].indexOf(role) > -1) {
        return true
      }
      if (this.user.access.indexOf('ROLE_ROOT') > -1) {
        return ['ROLE_ROOT'].indexOf(role) > -1
      }
      if (this.user.access.indexOf('ROLE_SCHOOL_ADMIN') > -1) {
        return ['ROLE_ROOT', 'ROLE_SCHOOL_ADMIN'].indexOf(role) > -1
      }
      if (this.user.access.indexOf('ROLE_INSTITUTE_ADMIN') > -1) {
        return ['ROLE_ROOT', 'ROLE_SCHOOL_ADMIN', 'ROLE_INSTITUTE_ADMIN'].indexOf(role) > -1
      }
      return false
    },
    // 清除表单数据
    resetFormData () {
      this.userForm = {
        id: this.userForm.id,
        department: this.user.department,
        teacher_code: '',
        student_code: '',
        code: null,
        name: null,
        tel: null,
        email: null,
        // 用户状态
        enabled: 'true',
        // 身份：教师 Teacher，学生 Student
        identity: 'Teacher',
        // 权限数组
        roles: ['ROLE_TEACHER', 'ROLE_USER']
      }
    },
    // 提交表单
    async handleSaveUser (name) {
      this.$refs[name].validate(async (valid) => {
        if (valid) {
          this.loading.submit = true
          try {
            let data = JSON.parse(JSON.stringify(this.userForm))
            data.enabled = (data.enabled === 'true')
            if (data.identity === 'Teacher') {
              data.code = data.teacher_code
              data.name = data.teacher_name
            } else {
              data.code = data.student_code
            }
            delete data.teacher_code
            delete data.teacher_name
            delete data.student_code
            // 处理可能会被输入的多余空格
            let needTrim = ['name', 'code', 'email', 'tel']
            needTrim.forEach(item => {
              data[item] = data[item] ? trim(data[item]) : data[item]
            })
            let response = await submitSaveUser(JSON.stringify(data))
            let res = response.data
            if (res.code) {
              this.$emit('saveSuccess', this.isModified)
            } else {
              this.$Notice.error({
                title: '提交失败',
                desc: (this.isModified ? '修改用户信息失败，' : '新增用户失败，') + res.info
              })
            }
          } catch (error) {
            this.$Notice.error({
              title: '提交失败',
              desc: (this.isModified ? '修改用户信息失败，' : '新增用户失败，') + error
            })
          }
          this.loading.submit = false
        } else {
          this.$Notice.error({
            title: '提交失败',
            desc: '抱歉，无法提交，请先完善表单信息再提交。'
          })
        }
      })
    },
    // 重置表单（清除验证和数据）
    handleReset (name) {
      this.$refs[name].resetFields()
      if (this.isModified) {
        this.userForm = {...this.beModifiedUser}
      } else {
        this.resetFormData()
      }
    },
    // 重置用户权限
    handleResetRoles () {
      this.userForm.roles = this.beModifiedUser.roles
    },
    // 更新用户权限
    async handleSaveRoles () {
      this.loading.submit = true
      try {
        let res = await updateUserRoles(this.userId, this.userForm.roles)
        res = res.data
        if (res.code) {
          this.$emit('saveSuccess', this.isModified)
        } else {
          this.$Notice.error({
            title: '更改用户权限失败',
            desc: res.info
          })
        }
        this.loading.submit = false
      } catch (error) {
        this.loading.submit = false
        this.$Notice.error({
          title: '更改用户权限失败',
          desc: error
        })
      }
    },
    // 修改用户信息时，填充旧数据
    async fillFormByData (code) {
      this.loading.fill = true
      let detail = await this.getUserDetailByCode(code)
      // let tempRoles = this.options.oriRoles
      // this.options.roles = Object.keys(tempRoles).filter(key => {
      //   return !this.ifDisableThisRoleCheckbox(key)
      // })
      // try {
      //   this.options.department = await this.getInstituteOptions()
      // } catch (error) {
      //   this.$Notice.error({
      //     title: '获取学院列表失败',
      //     desc: error
      //   })
      // }
      if (!detail.data) {
        this.$emit('failFillFrom', detail.info)
        this.$nextTick(() => {
          this.loading.fill = false
        })
        return false
      }
      if (this.options.department.indexOf(detail.data.department) < 0) {
        this.options.department.push(detail.data.department)
        // this.reChooseInstitute = true
        // todo: 重新从数据库拉取信息
      }
      if (detail.data.identity === 'Teacher') {
        this.userForm.roles.push('ROLE_TEACHER')
        detail.data.teacher_code = detail.data.code
      } else {
        this.userForm.roles.push('ROLE_STUDENT')
        detail.data.student_code = detail.data.code
      }
      detail.data.enabled = detail.data.enabled ? 'true' : 'false'
      this.userForm = JSON.parse(JSON.stringify(detail.data))
      this.beModifiedUser = JSON.parse(JSON.stringify(detail.data))
      this.$nextTick(() => {
        this.loading.fill = false
      })
    },
    // 通过用户Code获取用户信息
    async getUserDetailByCode (code) {
      let detail = {
        data: null,
        info: ''
      }
      try {
        let res = await getUserByCode(code)
        res = res.data
        if (res.code) {
          detail = {
            data: res.data,
            info: ''
          }
        } else {
          // this.$Notice.error({
          //   title: '获取用户信息失败',
          //   desc: res.info
          // })
          detail.info = res.info
        }
      } catch (error) {
        // this.$Notice.error({
        //   title: '获取用户信息失败',
        //   desc: error
        // })
        detail.info = error
      }
      return detail
    },
    // 显示带文字提示的Spin
    showSpinWithTip (tip) {
      this.$Spin.show({
        render: h => {
          return h('div', { class: 'ivu-spin-large' }, [
            h('span', {
              class: 'ivu-spin-dot',
              style: {
                display: 'inline-block'
              }
            }),
            h('div', tip)
          ])
        }
      })
    },
    // 数组删除指定元素
    arrayRemoveValue (array, value) {
      let index = array.indexOf(value)
      if (index > -1) {
        array.splice(index, 1)
      }
    }
  },
  watch: {
    isModified: {
      handler: function (value) {
        if (value) {
          this.fillFormByData(this.userCode)
        }
      },
      immediate: true
    },
    'loading.submit': function (val) {
      this.$emit('triggerClosable', !val)
    }
  },
  computed: {
    loadingTip () {
      let tip = '处理中，请稍等...'
      if (this.loading.submit) {
        tip = this.isModified ? '修改权限中，请稍等...' : '保存用户中，请稍等...'
      } else if (this.loading.fill) {
        tip = '获取用户信息中，请稍等...'
      }
      return tip
    }
  },
  created: function () {
    if (this.isModified) {
      this.loading.fill = true
    }
    this.getUserInfo().then(response => {
      let res = response.data
      if (res.code) {
        this.user.code = this.$store.state.user.userCode // 教师工号
        this.user.name = this.$store.state.user.userName // 教师姓名
        this.user.access = this.$store.state.user.access // 教师权限
        this.user.department = this.$store.state.user.department || '' // 教师权限
      }
      // if (!this.isModified) {
      this.createdHandleOptions()
      // }
    }).catch(err => {
      this.$nextTick(() => {
        this.loading.fill = false
      })
      this.$Notice.error({
        title: '提示',
        desc: '获取用户信息失败！请重试！' + err
      })
      console.log(err)
    })
  },
  mounted: function () {
    // 全局配置Notice组件的属性
    this.$Notice.config({
      top: window.innerHeight / 3
    })
  },
  beforeDestroy () {
    this.$Notice.destroy()
  }
}
</script>

<style lang="less" scope>
  @import (reference) "../../assets/styles/common.less";
  .not-required-item {
    .ivu-form-item-label{
      padding-left: 10px;
    }
  }
  .spin-icon-load {
    color: #f36a31;
    margin-right: 10px;
    .animation(ani-spin, 1s, linear, 0s, infinite, normal, forwards);
  }
  .keyframes (ani-spin, {
    0% {
      .transform(rotate(0));
    }
    50% {
      .transform(rotate(180deg));
    }
    100% {
      .transform(rotate(1turn));
    }
  });
</style>
